package com.opdar.athena.message.agent.client;

import com.opdar.athena.base.Message;
import com.opdar.athena.message.agent.TransferServer;
import com.opdar.athena.messages.HeartbeatMessage;
import com.opdar.athena.utils.MessageUtil;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.ReferenceCountUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.EOFException;
import java.net.InetSocketAddress;

/**
 * Created by shiju on 2017/6/27.
 */
public class ClientDecoder extends ChannelInboundHandlerAdapter {
    private byte[] project;
    private int version;
    private Logger logger = LoggerFactory.getLogger(getClass());

    public ClientDecoder(byte[] project) {
        this.project = project;
    }

    private byte[] byteBuf;

    @Override
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
        super.channelRegistered(ctx);
    }

    @Override
    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
        super.channelUnregistered(ctx);
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        //项目名称(fixed) 协议版本(int) 消息类型(short int) 长度(int) 消息内容(长度)
        ByteBuf byteBuf = (ByteBuf) msg;
        if (this.byteBuf != null) {
            byteBuf = Unpooled.wrappedBuffer(Unpooled.copiedBuffer(this.byteBuf), byteBuf);
            this.byteBuf = null;
        }
        while (byteBuf.readableBytes() > 0) {
            byteBuf.markReaderIndex();
            //验证协议
            if (byteBuf.readableBytes() < project.length) {
                //包长度不够,reset并退出
                byteBuf.resetReaderIndex();
                byteBuf.readBytes(this.byteBuf = new byte[byteBuf.readableBytes()]);
                break;
            }
            byte[] _project = new byte[project.length];
            byteBuf.readBytes(_project);
            if (compareProject(_project)) {
                if (byteBuf.readableBytes() >= 10) {
                    int version = byteBuf.readInt();
                    int type = byteBuf.readShort();
                    int length = byteBuf.readInt();
                    if (byteBuf.readableBytes() >= length) {
                        byte[] body = new byte[length];
                        byteBuf.readBytes(body);
                        Message message = MessageUtil.newMessageTypeInstance(type, body);
                        if (message != null) {
                            if(message instanceof HeartbeatMessage){
                                InetSocketAddress address = (InetSocketAddress) ctx.channel()
                                        .remoteAddress();
                                ClientPool pool = TransferServer.getServer().getContext().getBean(ClientPool.class);
                                long size = ((HeartbeatMessage) message).getTime();
                                Client client = pool.getClient(address);
                                client.setSize(size);
                                client.heartbeat();
                            }
                        }
                    } else {
                        byteBuf.resetReaderIndex();
                        byteBuf.readBytes(this.byteBuf = new byte[byteBuf.readableBytes()]);
                        break;
                    }
                } else {
                    byteBuf.resetReaderIndex();
                    byteBuf.readBytes(this.byteBuf = new byte[byteBuf.readableBytes()]);
                    break;
                }
            }
        }
        ReferenceCountUtil.safeRelease(byteBuf);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
    }

    private boolean compareProject(byte[] _project) throws EOFException {
        boolean ret = true;
        for (int i = 0; i < project.length; i++) {
            byte b = _project[i];
            if (project[i] != b) {
                ret = false;
                break;
            }
        }
        return ret;
    }

    public static void main(String[] args) {
        ByteBuf byteBuf = Unpooled.copiedBuffer(new byte[]{'t','e','s','t'});
        ByteBuf byteBuf2 = Unpooled.copiedBuffer(new byte[]{'1','2','3','4'});
        ByteBuf byteBuf3 = Unpooled.buffer(2);
        byteBuf.readBytes(byteBuf3);
        ByteBuf byteBuf4 = Unpooled.wrappedBuffer(byteBuf3,byteBuf2);
        byteBuf3.release();
        System.out.println(byteBuf4.array());
    }

}
